from zope.interface import implements
import os, sys

APPLICATION_INSTALL_DIR = os.environ.get('SIMPLEWATCHER_INSTALL')
if not APPLICATION_INSTALL_DIR:
    raise EnvironmentError("must set environment variable SIMPLEWATCHER_INSTALL")
sys.path.append('%s/lib' % APPLICATION_INSTALL_DIR)

from watcher.exceptions import *
from watcher import WatcherContainer, WatcherObject
from watcher.interfaces import IDecision, ICondition, ITestBehavior
from watcher.config.classbuilder import KlassBuilder


class Decision(WatcherContainer):
    """
    decisions to be made at particular points in an execute path.
    """
    implements(IDecision)
    def __init__(self, *args, **kwargs):
        super(Decision, self).__init__(*args, **kwargs)
        self.branches = []
    
    
    def run(self, workItem):
        """decision objects need a run method
           to act on a workItem.  conditions are tested against
           the workItem, and if they pass, their branch is added"""
        from docmanagement.watcher.branch import Branch
        for condition in self.config.condition:
            c = Condition('condition_%s' % condition.name, self.configPath, parent=self)
            for arg in c.config.test_behavior.arg:
                c.args[arg.name] = arg.xml_text_content()
            
            if c.test(workItem, c.args):
                self.branches.append(Branch("branch_%s" % condition.branch, self.configPath, parent=self))
        for branch in self.branches:
            branch.execute_path.execute(workItem)


class Condition(WatcherObject):
    """
    conditions to be matched by decisions
    """
    implements(ICondition)
    def __init__(self, *args, **kwargs):
        super(Condition, self).__init__(*args, **kwargs)
        test_behavior = "test_behavior_" + self.config.test_behavior.name
        self.test = KlassBuilder(test_behavior, self.configPath)()(test_behavior, self.configPath)
        self.args = {}
        if not ITestBehavior.providedBy(self.test):
            raise WatcherActionError("test behavior is invalid for %s" %
                                      self.config.name.xml_text_content())


class TestBehavior(WatcherObject):
    """the only requirement here is that __call__
       implement a kind of condition.test().
    """
    implements(ITestBehavior)

    def __call__(self):
        raise NotImplementedError("TestBehavior is abstract.  Subclass.")